from insts.inst import NoOperandInstruction


class RETURN_INST(NoOperandInstruction):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.kind = 'NULL'

    def execute(self, frame):
        thread = frame.getJThread()
        currentFrame = thread.popFrame()
        invokeFrame = thread.topFrame()
        if self.kind == 'void':
            return
        elif self.kind == 'int':
            invokeFrame.getOperandStack().pushInt(currentFrame.getOperandStack().popInt())

        elif self.kind == 'long':
            invokeFrame.getOperandStack().pushLong(currentFrame.getOperandStack().popLong())

        elif self.kind == 'float':
            invokeFrame.getOperandStack().pushFloat(currentFrame.getOperandStack().popFloat())

        elif self.kind == 'double':
            invokeFrame.getOperandStack().pushDouble(currentFrame.getOperandStack().popDouble())

        elif self.kind == 'ref':
            invokeFrame.getOperandStack().pushRef(currentFrame.getOperandStack().popRef())

        else:
            raise Exception("Invalid return type")


class RETURN(RETURN_INST):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.kind = 'void'


class IRETURN(RETURN_INST):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.kind = 'int'


class LRETURN(RETURN_INST):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.kind = 'long'


class FRETURN(RETURN_INST):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.kind = 'float'


class DRETURN(RETURN_INST):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.kind = 'double'


class ARETURN(RETURN_INST):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.kind = 'ref'
